package com.junyuan.gsp.web;

import com.junyuan.gsp.bean.Result;
import com.junyuan.gsp.bean.User;
import com.junyuan.gsp.service.UserService;
import com.junyuan.gsp.util.CipherUtil;
import com.junyuan.gsp.util.JWTUtil;
import com.junyuan.gsp.util.SubjectUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: maxwellens
 */
@RestController
public class UserController
{
    @Autowired
    private UserService userService;
    @Autowired
    private HttpServletRequest request;

    @GetMapping("/users/{id}")
    public Result findUserById(@PathVariable Integer id)
    {
        return new Result(userService.findUserById(id));
    }

    @GetMapping("/users/{id}/toggle-state")
    public Result toggleUserState(@PathVariable Integer id)
    {
        userService.toggleState(id);
        return Result.SUCCESS;
    }

    @GetMapping("/users")
    public Result findUsers(Integer page, Integer limit, String name)
    {
        Map<String, Object> map = new HashMap<>();
        map.put("page", page);
        map.put("limit", limit);
        map.put("name", name);
        return userService.findUsersResult(map);
    }

    @DeleteMapping("/users/{id}")
    public Result deleteUserById(@PathVariable Integer id)
    {
        userService.deleteUserById(id);
        return Result.SUCCESS;
    }

    @PutMapping("/users")
    public Result saveUser(User user)
    {
        userService.saveUser(user);
        return Result.SUCCESS;
    }

    /**
     * 当前登录用户
     *
     * @return
     */
    @GetMapping("/users/current")
    public Result getCurrentUser()
    {
        String account = SubjectUtil.getUser().getAccount();
        User user = userService.findUserByAccount(account);
        return new Result(user);
    }

    /**
     * 管理员快速登录（仅供调试，本地可用）
     *
     * @return
     */
    @GetMapping("/users/admin-login")
    public Result adminLogin()
    {
        String username = "admin";
        String password = User.DEFAULT_PASSWORD;
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        Subject subject = SecurityUtils.getSubject();
        String host = subject.getSession().getHost();
        if ("127.0.0.1".equals(host))
        {
            subject.login(token);
            User user = userService.findUserByAccount(username);
            return new Result(0, "登录成功", user);
        } else
        {
            throw new RuntimeException("当前无法使用管理员快速登录");
        }
    }

    /**
     * 用户登录
     *
     * @param username
     * @param password
     * @return
     */
    @PostMapping("/users/login")
    public Result login(String username, String password)
    {
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        Subject subject = SecurityUtils.getSubject();
        try
        {
            subject.login(token);
        } catch (AuthenticationException ex)
        {
            return new Result(1, "用户名不存在，或密码不正确", null);
        }
        User user = userService.findUserByAccount(username);
        SavedRequest savedRequest = WebUtils.getSavedRequest(request);
        String callbackUrl = "/";
        if (savedRequest != null)
        {
            String url = savedRequest.getRequestUrl();
            if (url.contains(".html"))
            {
                callbackUrl = url;
            }
        }
        return new Result(0, "登录成功", callbackUrl);
    }


    /**
     * jwt(JSON Web Token)登录
     *
     * @param username
     * @param password
     * @return
     */
    @PostMapping("/users/jwt-login")
    public Result jwtLogin(String username, String password)
    {
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        Subject subject = SecurityUtils.getSubject();
        try
        {
            subject.login(token);
        } catch (AuthenticationException ex)
        {
            return new Result(1, "用户名不存在，或密码不正确", null);
        }
        User user = userService.findUserByAccount(username);
        String encodedPassword = CipherUtil.encrypt(username, password);
        String jwt = JWTUtil.sign(username, encodedPassword);
        Map<String, Object> map = new HashMap<>();
        map.put("user", user);
        map.put("token", jwt);
        return new Result(0, "登录成功", map);
    }

    /**
     * 刷新登录，换取新的JWT
     *
     * @return
     */
    @GetMapping("/users/jwt-refresh")
    public Result jwtRefresh()
    {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated())
        {
            User user = SubjectUtil.getUser();
            String jwt = JWTUtil.sign(user.getAccount(), user.getPassword());
            Map<String, Object> map = new HashMap<>();
            map.put("user", user);
            map.put("token", jwt);
            return new Result(0, "登录成功", map);
        } else
        {
            return new Result(-1, "认证失败，请重新登录", null);
        }
    }

    /**
     * 心跳请求，保持登录状态
     *
     * @return
     */
    @GetMapping("/users/keepalive")
    public Result keepalive()
    {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated())
        {
            return Result.SUCCESS;
        } else
        {
            return new Result("用户已注销");
        }
    }

    /**
     * 用户注销
     *
     * @return
     */
    @GetMapping("/users/logout")
    public Result logout()
    {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated())
        {
            subject.logout();
            return new Result(0, "注销成功", null);

        } else
        {
            return new Result(0, "用户未登录", null);
        }
    }

    /**
     * 重置密码
     *
     * @return
     */
    @GetMapping("/users/{id}/reset-password")
    public Result resetPassword(@PathVariable Integer id)
    {
        userService.resetPassword(id);
        return Result.SUCCESS;
    }

    /**
     * 修改密码
     *
     * @param oldPassword 原密码
     * @param newPassword 新密码
     * @param rePassword  重复新密码
     * @return
     */
    @PutMapping("/users/change-password")
    public Result resetPassword(String oldPassword, String newPassword, String rePassword)
    {
        if (StringUtils.isEmpty(oldPassword))
        {
            return new Result(1, "原密码不能为空", null);
        }
        if (StringUtils.isEmpty(newPassword))
        {
            return new Result(1, "新密码不能为空", null);
        }
        if (StringUtils.isEmpty(rePassword))
        {
            return new Result(1, "新密码重复不能为空", null);
        }
        if (oldPassword.length() < 6 || newPassword.length() < 6 || rePassword.length() < 6)
        {
            return new Result(1, "密码长度至少六位", null);
        }
        if (!newPassword.equals(rePassword))
        {
            return new Result(1, "新密码和确认密码不一致", null);
        }
        if (SubjectUtil.getUser() == null)
        {
            return new Result(1, "未登录，请重新登录系统", null);
        }
        String account = SubjectUtil.getUser().getAccount();
        User user = userService.findUserByAccount(account);
        String encryptedOldPassword = CipherUtil.encrypt(user.getAccount(), oldPassword);
        if (!encryptedOldPassword.equals(user.getPassword()))
        {
            return new Result(1, "原密码不正确", null);
        }
        String encryptedNewPassword = CipherUtil.encrypt(user.getAccount(), newPassword);
        userService.changePassword(user.getId(), encryptedNewPassword);
        return Result.SUCCESS;
    }

}
